package task.presentation
{
    import flash.display.DisplayObject;

    import org.flexthinker.binding.form.FormModel;
    import org.flexthinker.binding.ui.form.binding.BindableUIForm;
    import org.flexthinker.binding.ui.form.binding.Binder;
    import org.flexthinker.binding.ui.form.binding.flex.RangeBinder;
    import org.flexthinker.binding.ui.form.binding.support.FormBinding;

    import spark.components.CheckBox;

    import spark.components.ComboBox;
    import spark.components.TextArea;
    import spark.components.TextInput;
    import spark.components.supportClasses.SkinnableComponent;
    import spark.components.supportClasses.SliderBase;

    import task.domain.TaskMetadata;
    import task.domain.converters.PriorityToIntConverter;

    /**
     * View displaying an editable <code>Task</code> form.
     */
    public class TaskForm extends SkinnableComponent implements BindableUIForm
    {
        [SkinPart(required="false")]
        public var category:ComboBox;

        [SkinPart(required="true")]
        public var title:TextInput;

        [SkinPart(required="false")]
        public var description:TextArea;

        [SkinPart(required="false")]
        public var priority:SliderBase;

        [SkinPart(required="false")]
        public var isPublic:CheckBox;

        /**
         * Form Model, wrapper for <code>task</code> property.
         */
        private var _formModel:FormModel;

        /**
         * For form binding used to bind the <code>task</code> to the ui fields.
         */
        private var formBinding:FormBinding;

        private var metadata:TaskMetadata = new TaskMetadata();


        public function TaskForm()
        {
            super();
        }

        public function setMetadata( taskMetadata:TaskMetadata ):void
        {
            if ( taskMetadata == null )
            {
                return;
            }
            metadata.categories = taskMetadata.categories;
            metadata.priorities = taskMetadata.priorities;
        }

        public function set formModel( formModel:FormModel ):void
        {
            _formModel = formModel;
            bind();
        }


        public function getBindableElements():Vector.<DisplayObject>
        {
            return new <DisplayObject>[category,  title,  description, priority, isPublic];
        }


        // --------------------
        //   internal methods
        // --------------------

        private function bind():void
        {
            if ( formBinding )
            {
                formBinding.unbind();
            }
            formBinding = new FormBinding(this,_formModel);

            // We need to add a special converter for the Priority.
            // Because in the TaskMetadata the priorities are reversed, meaning
            // the Low priority is marked as a 4, and the highest priority is 1, we need to
            // adapt those to the slider, which goes from 1 to 4.
            var priorityBinder:Binder = new RangeBinder(priority, "priority");
            priorityBinder.getBinding(_formModel).setConverter(new PriorityToIntConverter(metadata.priorities));
            formBinding.addFieldBinder(priorityBinder);

            // mark to auto bind ui fields; field name must match model property name
            formBinding.autoBind();
            //start binding
            formBinding.bind();
        }

        override protected function partAdded(partName:String, instance:Object):void
        {
            super.partAdded(partName, instance);
            switch( instance )
            {
                case category:
                    category.dataProvider = metadata.categories;
                    break;
            }
        }
    }
}
